<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
     /* 
        //以下边的使用案例举例
          在这个函数中,可以通过this拿到fn
          目标:调用fn   把fn的this指向context  返回fn的返回值
      */

      /* 
            fn1.call({}); //fn1的this指向对象{}
            fn1.call(null); //fn1的this指向对象window
            fn1.call(undefined); //fn1的this指向对象window
            fn1.call(1); //fn1的this指向对象 Object(1)
            fn1.call("abc"); //fn1的this指向对象{} Object("abc") */
    // Function.prototype.myCall = function (context, ...arg) {
     

    //   //对context判断
    //   if (context === null || context === undefined) {
    //     context = window;
    //   }
    //   if (typeof context !== "object" && typeof context !== "function") {
    //     context = Object(context);
    //   }


    //   //给context扩展一个属性 值为fn(this)
    //   const sy1 = Symbol('sy1');
    //   // myCall是被fn调用的所以这里this是指向的fn
    //   context[sy1] = this;

    //   //调用context新扩展的方法 context新增的属性所代表的fn就会调用,并把this指向context fn的返回值也会被re接收
    //   const re = context[sy1](...arg);

    //   //用完这个sy1属性 就删掉 不要对原context对象产生影响
    //   delete context[sy1];

    //   return re;
    // }




    // function fn(a, b) {
    //   console.log(this, a + b)
    //   return 1;
    // }
    // // 因为第一个参数身上有一个属性值为fn，所以调用之后fn的this指向就是第一个参数
    // console.log(fn.myCall({1:"1"}, 1, 2))



 // Function.prototype.mycall = function (context, ...arg) {
    //   // 如果值为null或者undefined则this指向window
    //   if (context === null && context === undefined) {
    //     context = window
    //   }
    //   if (typeof context !== "object" && typeof context !== "function") {
    //     context = Object(context)
    //   }
    //   // 申明一个独一无二的属性
    //   const sy1 = Symbol("sy1")
    //   // 给context上添加这个属性值为this(fn)
    //   context[sy1] = this
    //   const re = context[sy1](...arg)
    //   delete context[sy1]
    //   return re
    // }



    // function fn(a, b) {
    //   console.log(this, a + b);
    //   return 1
    // }
    // console.log(fn.mycall({}, 1, 2));



    // Function.prototype.mycall = function (context, ...arg) {
    //   if (context === null && context === undefined) {
    //     context = window
    //   }
    //   if (typeof context !== "object" && typeof context !== "function") {
    //     context = Object(context)
    //   }
    //   const sy1 = Symbol("sy1")
    //   context[sy1] = this
    //   const re = context[sy1](...arg)
    //   delete context[sy1]
    //   return re


    // }


    // function fn(a, b) {
    //   console.log(this, a + b);
    //   return 1
    // }

    // console.log(fn.mycall([], 1, 2));

    Function.prototype.mynew = function (context, ...arg) {
      if (context === null && context === undefined) {
        context = window
      }
      if (typeof context !== "object" && typeof context !== "function") {
        context = Object(context)
      }
      const sy1 = Symbol('sy1')
      context[sy1] = this
      const re = context[sy1](...arg)
      delete context[sy1]
      return re

    }

    function fn(a, b) {
      console.log(this, a + b);
      return 1
    }

    console.log(fn.mynew({}, 1, 2));


    
  </script>
</body>

</html>